home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / libs / knowhow4 / _farheap.asm next >
Assembly Source File  |  1992-06-11  |  32KB  |  768 lines

  1. ;[]-----------------------------------------------------------------[]
  2. ;|      FARHEAP.ASM                                                  |
  3. ;|                                                                   |
  4. ;|      C/C++ Run Time Library        Version 4.0                    |
  5. ;|                                                                   |
  6. ;|      Copyright (c) 1987, 1991 by Borland International Inc.       |
  7. ;|      All Rights Reserved.                                         |
  8. ;[]-----------------------------------------------------------------[]
  9.  
  10.         INCLUDE RULES.ASI
  11.  
  12.         LOCALS
  13.         INCLUDE _HEAP.INC
  14.  
  15.  
  16. ;-----------------------------------------------------------------------
  17. ; Memory Block Header (far heap)
  18. ;-----------------------------------------------------------------------
  19. ; Each block in the heap, whether allocated or free, has a header.
  20. ; For an allocated block, only the first two fields of the header are
  21. ; used. For a free block all ten bytes are used.  Blocks are aligned on
  22. ; paragraph boundaries, thus the smallest possible block sixteen bytes.
  23. ;
  24. ; Field       Description
  25. ; ---------   ----------------------------------------------------------
  26. ; size        total size, in paragraphs, of this block
  27. ; prev_real   segment of the physically previous block in the heap
  28. ;             prev_real is 0 this block is free, get the prev_real from prev_real2
  29. ; prev_free   segment of the logically previous free block
  30. ; next_free   segment of the logically next free block
  31. ; prev_real2  segment of the physically previous block in the heap
  32. ; free_space  first byte of free space available
  33. ;
  34. ; A doubly-linked queue is maintained of the free blocks and it is important 
  35. ; to know that ordering of the blocks in this queue is logical rather than 
  36. ; physical.  If there is only one free block on the heap prev_free and 
  37. ; next_free point to itself.
  38. ;-----------------------------------------------------------------------
  39. bsize           EQU     0
  40. prev_real       EQU     2
  41. prev_free       EQU     4
  42. next_free       EQU     6
  43. prev_real2      EQU     8
  44. free_space      EQU     10
  45.  
  46. ;-----------------------------------------------------------------------
  47. ; heapinfo structure (far heap)
  48. ;-----------------------------------------------------------------------
  49. ; Used by the heapwalk function.
  50. ; heapwalk accepts a pointer to a struct of this type.
  51. ; On entry, the pointer field contains the address of the previous
  52. ; memory block in the heap (NULL for the first call).  The next block
  53. ; in the heap is then found and its address is stored in the structure 
  54. ; along with its size, in bytes, and a 'used' flag.
  55. ;-----------------------------------------------------------------------
  56. HeapInfo        STRUC
  57. hi_ptr          dd      ?
  58. hi_size         dd      ?
  59. hi_inuse        dw      ?
  60.                 ENDS
  61.  
  62. UsedHeaderSize  EQU     4
  63. FreeHeaderSize  EQU     10
  64.  
  65.                 EXTRN   __brk:NEAR, __sbrk:NEAR
  66. _TEXT           SEGMENT PUBLIC 'CODE'
  67.                 ASSUME CS:_TEXT        
  68.  
  69. ;-----------------------------------------------------------------------
  70. ; Only three variables are needed to efficiently manage the heap.
  71. ; These reside in our own code segment for speed.
  72. ; We also set aside some scratch save areas.
  73. ;-----------------------------------------------------------------------
  74.         PUBLIC  ___first,___last,___rover
  75. ;               ALIGN   2
  76. ___first        dw      0               ;segment of the first block
  77. ___last         dw      0               ;segment of the last block
  78. ___rover        dw      0               ;segment of an arbitrary free block
  79. data_seg        dw      ?               ;old ds save area
  80. save_hi         dw      ?               ;for realloc
  81. save_lo         dw      ?
  82.  
  83. ;-----------------------------------------------------------------------------
  84. ; Frees the last block on the heap
  85. ; free helper function
  86. ;-----------------------------------------------------------------------------
  87. ; Args:                 Pointer to the block (dx)
  88. ; Returns:              void
  89. ;-----------------------------------------------------------------------------
  90. FreeLastBlock   PROC    NEAR
  91.                 cmp     dx,cs:[___first]           ;are we freeing the ONLY block?
  92.                 je      @@KillHeap
  93.                 mov     ds,dx
  94.                 mov     ds,ds:[prev_real]       ;ds = next-to-last block
  95.                 cmp     WORD PTR ds:[prev_real],0       ;is the previous block used?
  96.                 je      @@PreviousBlockIsFree
  97. @@PreviousBlockIsUsed:
  98.                 mov     cs:___last,ds
  99.                 jmp     short @@Cleanup1
  100.  
  101. @@PreviousBlockIsFree:
  102.                 mov     ax,ds
  103.                 cmp     ax,cs:[___first]        ;is the previous block the
  104.                 je      @@ResetHeap             ;first block in the heap?
  105.                 mov     ax,ds:[prev_real2]
  106.                 mov     cs:___last,ax
  107.                 push    ds                      ;save for call to __brk
  108.                 xor     ax,ax
  109.                 push    ax
  110.                 call    PullFreeBlock
  111.                 mov     ds,cs:[data_seg]
  112.                 jmp     short @@Cleanup2
  113. @@ResetHeap:
  114.                 mov     dx,cs:[___first]
  115. @@KillHeap:
  116.                 mov     cs:___first,0
  117.                 mov     cs:___last,0
  118.                 mov     cs:___rover,0
  119. @@Cleanup1:
  120.                 mov     ds,cs:[data_seg]
  121.                 push    dx
  122.                 xor     ax,ax
  123.                 push    ax
  124. @@Cleanup2:
  125.                 call    __brk                   ;reset the break level
  126.                 add     sp,4                    ;cleanup stack
  127.                 ret
  128.                 ENDP
  129.  
  130. ;-----------------------------------------------------------------------------
  131. ; Frees an interior block from within the heap
  132. ; free helper function
  133. ;-----------------------------------------------------------------------------
  134. ; Args:                 Pointer to the block (dx)
  135. ; Returns:              void
  136. ;-----------------------------------------------------------------------------
  137. FreeInnerBlock  PROC    NEAR
  138.                 mov     ds,dx                   ;ds = block to free
  139.                 push    ds                      ;save block address
  140.                 mov     es,ds:[prev_real]       ;es = previous block
  141.                 mov     WORD PTR ds:[prev_real],0       ;mark the block as free
  142.                 mov     ds:[prev_real2],es      
  143.                 cmp     dx,cs:[___first]           ;freeing first block?
  144.                 je      @@PreviousBlockIsUsed
  145.                 cmp     WORD PTR es:[prev_real],0       ;is the previous block free?
  146.                 jne     @@PreviousBlockIsUsed
  147. @@PreviousBlockIsFree:
  148.                 mov     ax,ds:[bsize]           ;ax = size of this block
  149.                 pop     bx
  150.                 push    es
  151.                 add     es:[bsize],ax           ;add it to the previous block
  152.                 mov     cx,es                   ;cx = previous block
  153.                 add     dx,ax                   ;dx = next block
  154.                 mov     es,dx                   ;es = next block
  155.                 cmp     WORD PTR es:[prev_real],0
  156.                 jne     @@NextBlockIsUsed
  157. @@NextBlockIsFree:
  158.                 mov     es:[prev_real2],cx
  159.                 jmp     SHORT @@CheckNextBlock
  160. @@NextBlockIsUsed:
  161.                 mov     es:[prev_real],cx
  162.                 jmp     SHORT @@CheckNextBlock
  163.  
  164. @@PreviousBlockIsUsed:
  165.                 call    InsertFreeBlock
  166.  
  167. @@CheckNextBlock:
  168.                 pop     es                      ;es = retrieve block
  169.                 mov     ax,es                   ;ax = block
  170.                 add     ax,es:[bsize]           ;ax = next block
  171.                 mov     ds,ax                   ;ds = next block
  172.                 cmp     WORD PTR ds:[prev_real],0       ;is next block free?
  173.                 je      JoinFreeBlocks
  174. @@AllDone:
  175.                 ret
  176.                 ENDP
  177.  
  178. ;-----------------------------------------------------------------------------
  179. ; Joins two physically adjacent free blocks together
  180. ; free helper function
  181. ;-----------------------------------------------------------------------------
  182. ; Args:                 Pointer to the lower block (es)
  183. ;                       Pointer to the upper block (ds)
  184. ; Returns:              void
  185. ; This routine falls through to PullFreeBlock
  186. ;-----------------------------------------------------------------------------
  187. JoinFreeBlocks  PROC    NEAR
  188.                 mov     ax,ds:[bsize]           ;ax = size of upper block
  189.                 add     es:[bsize],ax           ;add it to lower block size
  190.                 mov     ax,es                   ;ax = lower block
  191.                 mov     bx,ds                   ;bx = upper block
  192.                 add     bx,ds:[bsize]           ;bx = next block
  193.                 mov     es,bx                   ;es = next block
  194.                 mov     es:[prev_real],ax       ;fixup link
  195. ;;;;            jmp     SHORT PullFreeBlock
  196.                 ENDP
  197.  
  198. ;-----------------------------------------------------------------------------
  199. ; Removes a block from the free block queue
  200. ; free helper function
  201. ; malloc helper function
  202. ;-----------------------------------------------------------------------------
  203. ; Args:                 Pointer to the block (ds)
  204. ; Returns:              void
  205. ;-----------------------------------------------------------------------------
  206. PullFreeBlock   PROC    NEAR
  207.                 mov     bx,ds                   ;bx = this block
  208.                 cmp     bx,ds:[next_free]       ;only ONE free block?
  209.                 je      @@NoFreeBlocks
  210.                 mov     es,ds:[next_free]       ;es = next free block
  211.                 mov     ds,ds:[prev_free]       ;ds = previous free block
  212.                 mov     ds:[next_free],es
  213.                 mov     es:[prev_free],ds
  214.                 mov     cs:___rover,ds
  215.                 mov     ds,bx
  216.                 ret
  217. @@NoFreeBlocks:
  218.                 mov     cs:___rover,0
  219.                 ret
  220.                 ENDP
  221.  
  222. ;-----------------------------------------------------------------------------
  223. ; Inserts a block into the free block queue
  224. ; free helper function
  225. ;-----------------------------------------------------------------------------
  226. ; Args:                 Pointer to the block (ds)
  227. ; Returns:              void
  228. ;-----------------------------------------------------------------------------
  229. InsertFreeBlock PROC    NEAR
  230.                 mov     ax,cs:[___rover]        ;ax = rover pointer
  231.                 or      ax,ax                   ;no free blocks?
  232.                 jz      @@FirstFreeBlock
  233.                 mov     bx,ss                   ;save ss
  234.                 pushf                           ;save interrupt flag
  235.                 cli                             ;disable interrupts
  236.                 mov     ss,ax                   ;ss = rover pointer
  237.                 mov     es,ss:[next_free]       ;es = next free block
  238.                 mov     ss:next_free,ds         ;fixup links
  239.                 mov     ds:prev_free,ss
  240.                 mov     ss,bx                   ;restore ss
  241.                 popf                            ;restore interrupt flag
  242.                 mov     es:prev_free,ds
  243.                 mov     ds:next_free,es
  244.                 ret
  245.  
  246. @@FirstFreeBlock:
  247.                 mov     cs:___rover,ds
  248.                 mov     ds:[prev_free],ds
  249.                 mov     ds:[next_free],ds
  250.                 ret
  251.                 ENDP
  252.  
  253.  
  254. ;-----------------------------------------------------------------------------
  255. ; C callable function to free a memory block
  256. ;-----------------------------------------------------------------------------
  257. ; Args:                 Pointer to the block to free (stack)
  258. ; Returns:              void
  259. ;-----------------------------------------------------------------------------
  260. IF LDATA
  261.         PUBLIC  __free
  262. __free           LABEL   DIST
  263. ENDIF
  264.         PUBLIC  __farfree
  265. __farfree        PROC DIST
  266.         ARG     O:word, S:word
  267.  
  268.         push    bp
  269.         mov     bp,sp
  270.  
  271.         push    si
  272.         push    di
  273.  
  274.         mov     cs:data_seg,ds
  275.         mov     dx,[S]                  ;dx = segment to free
  276.         or      dx,dx                   ;is it NULL
  277.         jz      @@AllDone               ;   yes, skip it
  278.         cmp     dx,cs:[___last]         ;last block in the heap?
  279.         jne     @@InnerBlock
  280. @@LastBlock:
  281.         call    FreeLastBlock
  282.         jmp     SHORT @@AllDone
  283. @@InnerBlock:
  284.         call    FreeInnerBlock
  285. @@AllDone:
  286.                 mov     ds,cs:[data_seg]
  287.                 pop     di
  288.                 pop     si
  289.                 pop     bp
  290.                 ret
  291.                 ENDP
  292.  
  293. ;-----------------------------------------------------------------------------
  294. ; Creates a heap from scratch
  295. ; malloc helper function
  296. ;-----------------------------------------------------------------------------
  297. ; Args:                 Number of paragraphs for the first block requested (ax)
  298. ; Returns:              Address of the first byte of user space available
  299. ;                       from the heap if successful (dx:ax)
  300. ;                       NULL if failure (dx:ax)         
  301. ;-----------------------------------------------------------------------------
  302. CreateHeap      PROC    NEAR
  303.                 push    ax                      ;save the size
  304.  
  305.                 mov     ds,cs:[data_seg]
  306.                 xor     ax,ax                   ;align the heap on paragraph
  307.                 push    ax
  308.                 push    ax
  309.                 call    __sbrk                  ;retrieve the break level
  310.                 add     sp,4                    ;cleanup stack
  311.                 and     ax,000fh
  312.                 jz      @@Aligned
  313.                 mov     dx,16d
  314.                 sub     dx,ax
  315.                 xor     ax,ax
  316.                 mov     ds,cs:[data_seg]
  317.                 push    ax
  318.                 push    dx
  319.                 call    __sbrk                  ;align the heap
  320.                 add     sp,4                    ;cleanup stack
  321. @@Aligned:
  322.                 pop     ax                      ;retrieve and save the size
  323.                 push    ax
  324.  
  325.                 xor     bx,bx                   ;convert size to long in bx:ax
  326.                 mov     bl,ah
  327.                 mov     cl,4
  328.                 shr     bx,cl
  329.                 shl     ax,cl
  330.  
  331.                 mov     ds,cs:[data_seg]
  332.                 push    bx
  333.                 push    ax
  334.                 call    __sbrk                  ;adjust the break level
  335.                 add     sp,4                    ;cleanup stack
  336.  
  337.                 pop     bx                      ;retrieve the size
  338.  
  339.                 cmp     ax,-1                   ;failure?
  340.                 je      @@NoRoom
  341.  
  342.                 mov     cs:___first,dx          ;update heap pointers
  343.                 mov     cs:___last,dx
  344.                 mov     ds,dx
  345.                 mov     WORD PTR ds:[bsize],bx
  346.                 mov     WORD PTR ds:[prev_real],dx   ;just so we know it is used
  347.                 mov     ax,UsedHeaderSize
  348.                 ret
  349. @@NoRoom:
  350.                 xor     ax,ax
  351.                 cwd
  352.                 ret
  353.                 ENDP
  354.  
  355. ;-----------------------------------------------------------------------------
  356. ; Attempts to extend the heap.
  357. ; malloc helper function
  358. ;-----------------------------------------------------------------------------
  359. ; Args:                 Number of paragraphs for the block requested (ax)
  360. ; Returns:              Address of the first byte of user space available
  361. ;                       from the heap if successful (dx:ax)
  362. ;                       NULL if failure (dx:ax)         
  363. ;-----------------------------------------------------------------------------
  364. ExtendHeap      PROC    NEAR
  365.                 push    ax                      ;save the size
  366.  
  367.                 xor     bx,bx                   ;convert size to long in bx:ax
  368.                 mov     bl,ah
  369.                 mov     cl,4
  370.                 shr     bx,cl
  371.                 shl     ax,cl
  372.  
  373.                 mov     ds,cs:[data_seg]
  374.                 push    bx
  375.                 push    ax
  376.                 call    __sbrk                  ;adjust the break level
  377.                 add     sp,4                    ;cleanup stack
  378.  
  379.                 pop     bx                      ;retrieve the size
  380.  
  381.                 cmp     ax,-1                   ;failure?
  382.                 je      @@NoRoom
  383.  
  384.                 and     ax,0fh                  ;is it paragraph aligned?
  385.                 jnz     @@Misaligned            ;no - go adjust it
  386. @@GotBlock:
  387.                 mov     cx,cs:[___last]         ;cx = old last-block pointer
  388.                 mov     cs:___last,dx           ;update last-block pointer
  389.                 mov     ds,dx
  390.                 mov     WORD PTR ds:[bsize],bx
  391.                 mov     WORD PTR ds:[prev_real],cx
  392.                 mov     ax,UsedHeaderSize
  393.                 ret
  394.  
  395. ; Come here if the break level is not aligned on a paragraph boundary,
  396. ; which sometimes happens if both sbrk() and malloc() are used.  Adjust the
  397. ; break level and the block address up to the next paragraph boundary.
  398. ; The block segment is in DX; the low nibble of the offset is in AX.
  399.  
  400. @@Misaligned:
  401.                 push    bx                      ;save size again
  402.                 push    dx                      ;save segment of block
  403.                 neg     ax                      ;compute 16 - low nibble
  404.                 add     ax,16                   ;to get adjustment amount
  405.                 xor     bx,bx
  406.                 push    bx
  407.                 push    ax
  408.                 call    __sbrk                  ;allocate extra bytes
  409.                 add     sp,4                    ;clean up stack
  410.                 pop     dx                      ;recover segment
  411.                 pop     bx                      ;recover size
  412.                 cmp     ax,-1                   ;failure
  413.                 je      @@NoRoom
  414.                 inc     dx                      ;skip to next paragraph
  415.                 jmp     @@GotBlock
  416. @@NoRoom:
  417.                 xor     ax,ax
  418.                 cwd
  419.                 ret
  420.                 ENDP
  421.  
  422. ;-----------------------------------------------------------------------------
  423. ; Divides a free block into two pieces.
  424. ; malloc helper function
  425. ;-----------------------------------------------------------------------------
  426. ; Args:                 Number of paragraphs for the block requested (ax)
  427. ;                       Pointer of the block to divide (ds & dx)
  428. ; Returns:              Address of the first byte of user space available
  429. ;                       from the heap (dx:ax)
  430. ;-----------------------------------------------------------------------------
  431. AllocatePartialBlock    PROC    NEAR
  432.                 mov     bx,dx                   ;save block
  433.                 sub     ds:[bsize],ax           ;make room for new block
  434.                 add     dx,ds:[bsize]
  435.                 mov     ds,dx                   ;ds = new block
  436.                 mov     ds:[bsize],ax
  437.                 mov     ds:[prev_real],bx
  438.                 mov     bx,dx                   ;save block
  439.                 add     bx,ds:[bsize]
  440.                 mov     ds,bx                   ;ds = next block
  441.                 mov     ds:[prev_real],dx
  442.                 mov     ax,UsedHeaderSize
  443.                 ret
  444.                 ENDP
  445.  
  446. ;-----------------------------------------------------------------------------
  447. ; C callable function to allocates a given number of bytes from the far heap
  448. ;-----------------------------------------------------------------------------
  449. ; Args:                 Number of bytes requested (long, stack)
  450. ; Returns:              Address of the first byte of user space available
  451. ;                       from the heap if successful (dx:ax)
  452. ;                       NULL if failure (ds:ax)         
  453. ;-----------------------------------------------------------------------------
  454.                 PROC    GenericMalloc DIST
  455. IF LDATA
  456.         PUBLIC  __malloc
  457. __malloc         LABEL   DIST
  458.                 ARG     R2:word
  459.  
  460.                 push    bp
  461.                 mov     bp,sp
  462.                 xor     dx,dx
  463.                 mov     ax,[R2]                 ;dx:ax = size requested (long)
  464.                 jmp     SHORT @@GotTheSize
  465. ENDIF
  466.         PUBLIC  __farmalloc
  467. __farmalloc      LABEL   DIST
  468.         ARG     R2:word, R1:word
  469.  
  470.                 push    bp
  471.                 mov     bp,sp
  472.                 mov     dx,[R1]
  473.                 mov     ax,[R2]                 ;dx:ax = size requested (long)
  474. @@GotTheSize:
  475.                 mov     cx,ax
  476.                 or      cx,dx                   ;does he want 0 bytes?
  477.                 push    si
  478.                 push    di
  479.                 mov     cs:data_seg,ds
  480.                 jz      @@AllDone
  481.                 add     ax,UsedHeaderSize+15    ;add the header size and
  482.                 adc     dx,0                    ;force paragraph boundary
  483.                 jc      @@NoCanDo               ;size too big?
  484.                 test    dx,0fff0h
  485.                 jnz     @@NoCanDo               ;size too big?
  486.                 mov     cl,4
  487.                 shr     ax,cl
  488.                 shl     dx,cl
  489.                 or      ah,dl                   ;ax = number of paragraphs
  490.  
  491.                 mov     dx,cs:[___first]        ;dx = first block in the heap
  492.                 or      dx,dx                   ;is there any heap at all?
  493.                 jz      @@BuildHeap
  494.  
  495.                 mov     dx,cs:[___rover]        ;dx = rover pointer
  496.                 or      dx,dx
  497.                 jz      @@AddToHeap
  498.  
  499.                 mov     bx,dx                   ;bx = rover pointer
  500. @@SearchHeap:
  501.                 mov     ds,dx                   ;ds = free block
  502.                 cmp     ds:[bsize],ax           ;is it big enough?
  503.                 jae     @@AllocateBlock
  504. @@TooSmall:
  505.                 mov     dx,ds:[next_free]       ;dx = next free block
  506.                 cmp     dx,bx                   ;are we done?
  507.                 jne     @@SearchHeap
  508. @@AddToHeap:
  509.                 call    ExtendHeap
  510.                 jmp     SHORT @@AllDone
  511. @@BuildHeap:
  512.                 call    CreateHeap
  513.                 jmp     SHORT @@AllDone
  514. @@DivideFreeBlock:
  515.                 call    AllocatePartialBlock
  516.                 jmp     SHORT @@AllDone
  517. @@NoCanDo:
  518.                 xor     ax,ax
  519.                 cwd
  520.                 jmp     SHORT @@AllDone
  521. @@AllocateBlock:
  522.                 ja      @@DivideFreeBlock
  523.                 call    PullFreeBlock           ;remove it from the free-block queue
  524.                 mov     bx,ds:[prev_real2]      ;mark it as allocated
  525.                 mov     ds:[prev_real],bx
  526.                 mov     ax,UsedHeaderSize
  527. @@AllDone:
  528.                 mov     ds,cs:[data_seg]
  529.                 pop     di
  530.                 pop     si
  531. @@Exit:
  532.                 pop     bp
  533.                 ret
  534.                 ENDP
  535.  
  536. ;-----------------------------------------------------------------------------
  537. ; Attempts to expand a block, relocating it if necessary
  538. ; realloc helper function
  539. ;-----------------------------------------------------------------------------
  540. ; Args:                 Pointer to the old block (bx)
  541. ;                       Number of paragraphs requested (ax)
  542. ; Returns:              Address of the first byte of user space available
  543. ;                       from the heap if successful (dx:ax)
  544. ;                       NULL if failure (dx:ax)         
  545. ;-----------------------------------------------------------------------------
  546.  
  547. ExpandBlock     PROC    NEAR
  548.                 push    bx                      ;save the old block
  549.                 mov     si,cs:[save_hi]         ;get size parms from _farrealloc
  550.         push    si                      ;setup for _farmalloc
  551.                 mov     si,cs:[save_lo]         ;get size parms from _farrealloc
  552.         push    si                      ;setup for _farmalloc
  553.         call    __farmalloc
  554.                 add     sp,4                    ;cleanup stack
  555.                 or      dx,dx
  556.                 jnz     @@MallocOK
  557. @@MallocFailed:
  558.                 pop     bx                      ;cleanup stack
  559.                 ret
  560. @@MallocOK:
  561.                 pop     ds                      ;ds = old block
  562.                 mov     es,dx                   ;es = new block
  563.                 push    es                      ;save new block
  564.         push    ds                      ;save old block for _farfree
  565.                 push    bx
  566.  
  567.                 mov     dx,ds:[bsize]           ;dx = old block size
  568. @@MoveFirstBlock:
  569.                 cld
  570.                 dec     dx                      ;subtract one paragraph
  571.                 mov     di,UsedHeaderSize
  572.                 mov     si,di
  573.                 mov     cx,(16d-UsedHeaderSize)/2
  574.                 rep     
  575.                 movsw
  576.                 or      dx,dx
  577.                 jz      @@FreeOldBlock
  578.                 mov     ax,es                   ;increment segments
  579.                 inc     ax
  580.                 mov     es,ax
  581.                 mov     ax,ds
  582.                 inc     ax
  583.                 mov     ds,ax
  584. @@MoveLoop:
  585.                 xor     di,di
  586.                 mov     si,di
  587.                 mov     cx,dx                   ;cx = paragraphs remaining
  588.                 cmp     cx,1000h
  589.                 jbe     @@MoveIt
  590.                 mov     cx,1000h
  591. @@MoveIt:       shl     cx,1                    ;cx = number of words
  592.                 shl     cx,1
  593.                 shl     cx,1
  594.                 rep
  595.                 movsw
  596.                 sub     dx,1000h
  597.                 jbe     @@FreeOldBlock
  598.                 mov     ax,es                   ;increment segments
  599.                 add     ax,1000h                ;add 64k
  600.                 mov     es,ax
  601.                 mov     ax,ds
  602.                 add     ax,1000h                ;add 64k
  603.                 mov     ds,ax
  604.                 jmp     SHORT @@MoveLoop
  605. @@FreeOldBlock:
  606.                 mov     ds,cs:[data_seg]
  607.         call    __farfree                ;free the old block
  608.                 add     sp,4                    ;cleanup stack
  609.  
  610.                 pop     dx
  611.                 mov     ax,UsedHeaderSize
  612. @@AllDone:
  613.                 ret
  614.                 ENDP
  615.  
  616. ;-----------------------------------------------------------------------------
  617. ; Shrinks a block
  618. ; realloc helper function
  619. ;-----------------------------------------------------------------------------
  620. ; Args:                 Pointer to the block (bx)
  621. ;                       Size of the block (cx)
  622. ;                       Normalized number of paragraphs requested (ax)
  623. ; Returns:              Address of the first byte of user space available
  624. ;                       from the heap if successful (dx:ax)
  625. ;-----------------------------------------------------------------------------
  626.  
  627. ShrinkBlock     PROC    NEAR
  628.                 cmp     bx,cs:[___last]         ;last block in the heap?
  629.                 je      @@LastBlock
  630. @@InnerBlock:
  631.                 mov     di,bx                   ;di = old block
  632.                 add     di,ax                   ;di = new block
  633.                 mov     es,di                   ;es = new block
  634.                 mov     si,cx                   ;si = old block size
  635.                 sub     si,ax                   ;si -= new block size
  636.                 mov     es:[bsize],si           ;setup new block        
  637.                 mov     es:[prev_real],bx
  638.         push    es                      ;save for _farfree
  639.  
  640.                 push    ax
  641.  
  642.                 mov     es,bx                   ;es = original block
  643.                 mov     es:[bsize],ax
  644.                 mov     dx,bx                   ;dx = old block
  645.                 add     dx,cx                   ;dx = block after new
  646.                 mov     es,dx                   ;es = block after new
  647.                 cmp     WORD PTR es:[prev_real],0       ;is it used?
  648.                 je      @@NextIsFree
  649. @@NextIsUsed:
  650.                 mov     es:[prev_real],di
  651.                 jmp     SHORT @@UnlinkIt
  652. @@NextIsFree:
  653.                 mov     es:[prev_real2],di
  654. @@UnlinkIt:
  655.                 mov     si,bx                   ;si = old block
  656.         call    __farfree
  657.                 add     sp,4                    ;cleanup stack
  658.                 mov     dx,si
  659.                 mov     ax,UsedHeaderSize
  660.                 ret
  661. @@LastBlock:
  662.                 push    bx                      ;save block
  663.                 mov     es,bx
  664.                 mov     es:[bsize],ax
  665.                 add     bx,ax
  666.                 push    bx
  667.                 xor     ax,ax
  668.                 push    ax
  669.                 call    __brk                   ;reset the break level
  670.                 add     sp,4                    ;cleanup stack
  671.  
  672.                 pop     dx                      ;restore block
  673.                 mov     ax,UsedHeaderSize
  674.                 ret
  675.                 ENDP
  676.  
  677. ;-----------------------------------------------------------------------------
  678. ; Attempts to reallocate a block
  679. ;-----------------------------------------------------------------------------
  680. ; Args:                 Pointer to the old block (stack)
  681. ;                       Number of bytes requested (stack)
  682. ; Returns:              Address of the first byte of user space available
  683. ;                       from the heap if successful (dx:ax)
  684. ;                       NULL if failure (dx:ax)         
  685. ;-----------------------------------------------------------------------------
  686.                 PROC    GenericRealloc DIST
  687. IF LDATA
  688.         PUBLIC  __realloc
  689. __realloc        LABEL   DIST
  690.                 ARG     O:word, S:word, LO:word
  691.                 push    bp
  692.                 mov     bp,sp
  693.                 xor     dx,dx
  694.                 jmp     SHORT @@GetTheSize
  695. ENDIF
  696.         PUBLIC  __farrealloc
  697. __farrealloc     LABEL   DIST
  698.         ARG     O:word, S:word, LO:word, HI:word
  699.         push    bp
  700.         mov     bp,sp
  701.         mov     dx,[HI]
  702. @@GetTheSize:
  703.         mov     ax,[LO]                 ;dx:ax = size requested (long)
  704.         mov     bx,[S]                  ;bx = segment to realloc
  705.  
  706.         push    si
  707.         push    di
  708.         mov     cs:data_seg,ds
  709.         mov     cs:save_hi,dx
  710.         mov     cs:save_lo,ax
  711.  
  712.         or      bx,bx                   ;is it a null pointer?
  713.                 jz      @@MallocIt
  714.  
  715.                 mov     cx,ax
  716.                 or      cx,dx                   ;does he want 0 bytes?
  717.                 jz      @@FreeIt
  718.  
  719.                 add     ax,UsedHeaderSize+15    ;add the header size and
  720.                 adc     dx,0                    ;force paragraph boundary
  721.                 jc      @@RetNull               ;size too big?
  722.                 test    dx,0fff0h
  723.                 jnz     @@RetNull               ;size too big?
  724.                 mov     cl,4
  725.                 shr     ax,cl
  726.                 shl     dx,cl
  727.                 or      ah,dl                   ;ax = number of paragraphs
  728.  
  729.                 mov     es,bx                   ;es = segment to realloc
  730.                 mov     cx,es:[bsize]           ;cx = current block size
  731.                 cmp     cx,ax
  732.                 jb      @@ExpandIt
  733.                 ja      @@ShrinkIt
  734. @@NoChange:
  735.                 mov     dx,bx
  736.                 mov     ax,UsedHeaderSize
  737.                 jmp     SHORT @@AllDone
  738. @@ShrinkIt:
  739.                 call    ShrinkBlock
  740.                 jmp     SHORT @@AllDone
  741. @@ExpandIt:
  742.                 call    ExpandBlock
  743.                 jmp     SHORT @@AllDone
  744. @@MallocIt:
  745.                 push    dx
  746.                 push    ax
  747.         call    __farmalloc
  748.                 add     sp,4                    ;cleanup stack
  749.                 jmp     SHORT @@AllDone
  750. @@FreeIt:
  751.                 push    bx
  752.                 push    ax                      ;has a zero left over
  753.         call    __farfree
  754.                 add     sp,4                    ;cleanup stack
  755. @@RetNull:      
  756.                 xor     ax, ax
  757.                 cwd
  758. @@AllDone:
  759.                 mov     ds,cs:[data_seg]
  760.                 pop     di
  761.                 pop     si
  762.                 pop     bp
  763.                 ret
  764.                 ENDP
  765.  
  766.                 ENDS
  767.                 END
  768.